/*****************************************************************************\
 *  node_conf.h - definitions for reading the node part of slurm configuration
 *  file and work with the corresponding structures
 *****************************************************************************
 *  Copyright (C) 2002-2007 The Regents of the University of California.
 *  Copyright (C) 2008-2010 Lawrence Livermore National Security.
 *  Copyright (C) 2010-2016 SchedMD LLC.
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 *  Written by Morris Jette <jette1@llnl.gov> et. al.
 *  CODE-OCEC-09-009. All rights reserved.
 *
 *  This file is part of Slurm, a resource management program.
 *  For details, see <https://slurm.schedmd.com/>.
 *  Please also read the included file: DISCLAIMER.
 *
 *  Slurm is free software; you can redistribute it and/or modify it under
 *  the terms of the GNU General Public License as published by the Free
 *  Software Foundation; either version 2 of the License, or (at your option)
 *  any later version.
 *
 *  In addition, as a special exception, the copyright holders give permission
 *  to link the code of portions of this program with the OpenSSL library under
 *  certain conditions as described in each individual source file, and
 *  distribute linked combinations including the two. You must obey the GNU
 *  General Public License in all respects for all of the code used other than
 *  OpenSSL. If you modify file(s) with this exception, you may extend this
 *  exception to your version of the file(s), but you are not obligated to do
 *  so. If you do not wish to do so, delete this exception statement from your
 *  version.  If you delete this exception statement from all source files in
 *  the program, then also delete it here.
 *
 *  Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with Slurm; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
\*****************************************************************************/

#ifndef _HAVE_NODE_CONF_H
#define _HAVE_NODE_CONF_H

#include "config.h"

#include <inttypes.h>
#include <time.h>

#include "src/common/bitstring.h"
#include "src/common/hostlist.h"
#include "src/common/list.h"
#include "src/common/slurm_protocol_defs.h"
#include "src/common/slurm_protocol_socket_common.h"
#include "src/common/xhash.h"

#define CONFIG_MAGIC	0xc065eded
#define NODE_MAGIC	0x0de575ed

//slurm管理节点资源的方式
//节点配置描述符，对应节点配置文件中的一行，代表具有相同配置的大量节点
struct config_record {
	uint32_t magic;		/* magic cookie to test data integrity */
	uint16_t cpus;		/* 节点上运行的处理器数量	*/
	char *cpu_spec_list;	/* arbitrary list of specialized cpus 专用cpu的任意列表*/
	uint16_t boards;	/* 配置的boards数 */
	uint16_t sockets;	/* 每个节点sockets数 */
	uint16_t cores;		/* 每个socket的cores数 */
	uint16_t core_spec_cnt;	/* 专用核心数 */
	uint32_t cpu_bind;	/* 默认CPU绑定类型 */
	uint16_t threads;	/* 每个核心threads数 */
	uint64_t mem_spec_limit; /* MB 实际内存 for memory specialization */
	uint64_t real_memory;	/* MB 节点上实际内存 */
	uint32_t tmp_disk;	/* MB tmp_fs文件系统中的总存储空间	*/
	double  *tres_weights;	/* TRES权重数组 */
	char    *tres_weights_str; /* 每TRES计费权重字符串	*/
	uint32_t weight;	/* 用于调度工作的节点的任意优先级	*/
	char *feature;		/* 节点特性的任意列表	*/
	char *gres;		/* 节点通用资源的任意列表	*/
	char *nodes;		/* 具有此配置的节点的名称	*/
	bitstr_t *node_bitmap;	/* 具有此配置的节点的位图	*/
};
extern List config_list;	/* list of config_record entries */

extern List front_end_list;	/* list of slurm_conf_frontend_t entries */
//slurm管理节点资源的方式
//节点描述符，记录单个节点配置
struct node_record {
	uint32_t magic;			/* magic cookie 用于数据完整性 */
	char *name;			/* 节点名. NULL==defunct */
	uint32_t next_state;		/* 重启后状态 */
	char *node_hostname;		/* 节点hostname */
	uint32_t node_state;		/* 枚举节点状态 node_states, ORed with
					 * NODE_STATE_NO_RESPOND if not
					 * responding */
	bool not_responding;		/* 设置该值如果没有响应，日志记录后清除 */
	time_t boot_req_time;		/* 	节点启动请求的时间	*/
	time_t boot_time;		/* 节点启动时间,由up_time计算 */
	uint32_t cpu_bind;		/* 默认 CPU 绑定类型 */
	time_t slurmd_start_time;	/* slurmd启动时间 */
	time_t last_response;		/* 节点最后响应时间 */
	time_t last_idle;		/* 节点最后变空闲时间 */
	uint16_t cpus;			/* 节点上的处理器数	*/
	uint16_t boards; 		/* 配置的boards数 */
	uint16_t sockets;		/* 每个节点sockets数 */
	uint16_t cores;			/* 每个socket的核心数  */
	char *cpu_spec_list;		/* node's specialized cpus 	节点的专用cpu*/
	uint16_t core_spec_cnt;		/* number of specialized cores on node节点的专用cpu数量*/
	uint16_t threads;		/* 每个核心线程数 */
	uint64_t real_memory;		/* MB real memory on the node */
	uint64_t mem_spec_limit;	/* MB memory limit for specialization */
	uint32_t tmp_disk;		/* MB total disk in TMP_FS */
	uint32_t up_time;		/* 节点启动后的秒数	*/
	struct config_record *config_ptr;  /* 配置规格指针，指向节点所属的节点配置文件里面相应行对应的节点配置描述符 */
	uint16_t part_cnt;		/* 相关分区的数量	*/
	struct part_record **part_pptr;	/* 指向与此节点关联的分区的指针数组	*/
	char *comm_name;		/* 节点的通信路径名	*/
	uint16_t port;			/* slurmd的TCP端口号 */
	slurm_addr_t slurm_addr;	/* 网络地址 */
	uint16_t comp_job_cnt;		/* count of jobs completing on node */
	uint16_t run_job_cnt;		/* 节点上运行的作业数	*/
	uint16_t sus_job_cnt;		/* 节点上挂起的作业数 */
	uint16_t no_share_job_cnt;	/* 运行中不共享节点的作业数	*/
	char *reason; 			/* 节点DOWN或者DRAINING的原因 */
	time_t reason_time;		/* 	设置原因时的时间戳，如果未设置原因，则忽略	*/
	uint32_t reason_uid;		/* 设置原因的用户，如果没有设置原因，则忽略	*/
	char *features;			/* 节点的可用功能仅用于状态保存/还原，不用于调度目的	*/
	char *features_act;		/* 节点的活动特性仅用于状态保存/恢复，不用于调度目的	*/
	char *gres;			/* 节点的通用资源仅用于状态保存/恢复，不用于调度目的	*/
	List gres_list;			/* 由插件管理的gres状态信息列表	*/
	uint64_t sched_weight;		/* 用于调度目的的节点权重。cons_tres使用	*/
	uint32_t weight;		/* 原始权值，仅用于状态保存/恢复，不用于调度目的。*/
	char *arch;			/* 计算机体系结构 */
	char *os;			/* 正在运行的操作系统	*/
	struct node_record *node_next;	/* 下一个具有相同哈希索引的项	*/
	uint32_t node_rank;		/* 基于节点名称的希尔伯特数，或用于按位置对节点排序的其他序列号，不需要保存/恢复	*/
#ifdef HAVE_ALPS_CRAY
	uint32_t basil_node_id;		/* Cray-XT BASIL node ID,
					 * no need to save/restore */
	time_t down_time;		/* When first set to DOWN state */
#endif	/* HAVE_ALPS_CRAY */
	acct_gather_energy_t *energy;	/* 能耗数据	*/
	ext_sensors_data_t *ext_sensors; /* 外部传感器数据	*/
	power_mgmt_data_t *power;	/* 电源管理数据	*/
	dynamic_plugin_data_t *select_nodeinfo; /* 不透明的数据结构，使用select_g_get_nodeinfo()来访问内容 */
	uint32_t cpu_load;		/* CPU 负载 * 100 */
	time_t cpu_load_time;		/* cpu_load最后设置的时间 */
	uint64_t free_mem;		/* 空闲内存 in MiB */
	time_t free_mem_time;		/* 上次设置free_mem的时间	*/
	uint16_t protocol_version;	/* Slurm版本号	*/
	char *version;			/* Slurm版本 */
	bitstr_t *node_spec_bitmap;	/* node cpu specialization bitmap */
	uint32_t owner;			/* 允许使用节点的用户或者NO_VAL */
	uint16_t owner_job_cnt;		/* "owner"的独占作业数 */
	char *tres_str;                 /* 该节点有的tres, 1=2,2=3690,5=2*/
	char *tres_fmt_str;		/* 该节点有的tres, cpu=2,mem=3690M,billing=2*/
	uint64_t *tres_cnt;		/* tres this node has. NO_PACK*/
	char *mcs_label;		/* mcs_label if mcs plugin in use */
};
extern struct node_record *node_record_table_ptr;  /* 链表ptr to node records */
extern int node_record_count;		/* count in node_record_table_ptr */
extern xhash_t* node_hash_table;	/* 哈希表hash table for node records */
extern time_t last_node_update;		/* 上次node record更新时间 */

extern uint16_t *cr_node_num_cores;
extern uint32_t *cr_node_cores_offset;

/*
 * bitmap2node_name_sortable - given a bitmap, build a list of comma
 *	separated node names. names may include regular expressions
 *	(e.g. "lx[01-10]")
 * IN bitmap - bitmap pointer
 * IN sort   - returned ordered list or not
 * RET pointer to node list or NULL on error
 * globals: node_record_table_ptr - pointer to node table
 * NOTE: the caller must xfree the memory at node_list when no longer required
 */
char * bitmap2node_name_sortable (bitstr_t *bitmap, bool sort);

/*
 * bitmap2node_name - given a bitmap, build a list of comma separated node
 *	names. names may include regular expressions (e.g. "lx[01-10]")
 * IN bitmap - bitmap pointer
 * RET pointer to node list or NULL on error
 * globals: node_record_table_ptr - pointer to node table
 * NOTE: the caller must xfree the memory at node_list when no longer required
 */
char * bitmap2node_name (bitstr_t *bitmap);

/*
 * bitmap2hostlist - given a bitmap, build a hostlist
 * IN bitmap - bitmap pointer
 * RET pointer to hostlist or NULL on error
 * globals: node_record_table_ptr - pointer to node table
 * NOTE: the caller must xfree the memory at node_list when no longer required
 */
hostlist_t bitmap2hostlist (bitstr_t *bitmap);

/*
 * build_all_nodeline_info - get a array of slurm_conf_node_t structures
 *	from the slurm.conf reader, build table, and set values
 * IN set_bitmap - if true, set node_bitmap in config record (used by slurmd)
 * IN tres_cnt - number of TRES configured on system (used on controller side)
 * RET 0 if no error, error code otherwise
 */
extern int build_all_nodeline_info (bool set_bitmap, int tres_cnt);

/*
 * build_all_frontend_info - get a array of slurm_conf_frontend_t structures
 *	from the slurm.conf reader, build table, and set values
 * is_slurmd_context: set to true if run from slurmd
 * RET 0 if no error, error code otherwise
 */
extern int build_all_frontend_info (bool is_slurmd_context);

/*
 * create_config_record - create a config_record entry and set is values to
 *	the defaults. each config record corresponds to a line in the
 *	slurm.conf file and typically describes the configuration of a
 *	large number of nodes
 * RET pointer to the config_record
 * NOTE: memory allocated will remain in existence until
 *	_delete_config_record() is called to delete all configuration records
 */
extern struct config_record *create_config_record (void);

/*
 * create_node_record - create a node record and set its values to defaults
 * IN config_ptr - pointer to node's configuration information
 * IN node_name - name of the node
 * RET pointer to the record or NULL if error
 * NOTE: allocates memory at node_record_table_ptr that must be xfreed when
 *	the global node table is no longer required
 */
extern struct node_record *create_node_record (
			struct config_record *config_ptr, char *node_name);

/*
 * find_node_record - find a record for node with specified name
 * IN: name - name of the desired node
 * RET: pointer to node record or NULL if not found
 * NOTE: Logs an error if the node name is NOT found
 */
extern struct node_record *find_node_record (char *name);

/*
 * find_node_record2 - find a record for node with specified name
 * IN: name - name of the desired node
 * RET: pointer to node record or NULL if not found
 * NOTE: Does not log an error if the node name is NOT found
 */
extern struct node_record *find_node_record2 (char *name);

/*
 * find_node_record_no_alias - find a record for node with specified name
 * without looking at the node's alias (NodeHostName).
 * IN: name - name of the desired node
 * RET: pointer to node record or NULL if not found
 * NOTE: Does not log an error if the node name is NOT found
 */
extern struct node_record *find_node_record_no_alias (char *name);

/*
 * hostlist2bitmap - given a hostlist, build a bitmap representation
 * IN hl          - hostlist
 * IN best_effort - if set don't return an error on invalid node name entries
 * OUT bitmap     - set to bitmap, may not have all bits set on error
 * RET 0 if no error, otherwise EINVAL
 */
extern int hostlist2bitmap (hostlist_t hl, bool best_effort, bitstr_t **bitmap);

/*
 * init_node_conf - initialize the node configuration tables and values.
 *	this should be called before creating any node or configuration
 *	entries.
 * RET 0 if no error, otherwise an error code
 */
extern int init_node_conf (void);

/* node_fini2 - free memory associated with node records (except bitmaps) */
extern void node_fini2 (void);

/*
 * node_name2bitmap - given a node name regular expression, build a bitmap
 *	representation
 * IN node_names  - list of nodes
 * IN best_effort - if set don't return an error on invalid node name entries
 * OUT bitmap     - set to bitmap, may not have all bits set on error
 * RET 0 if no error, otherwise EINVAL
 * NOTE: the caller must bit_free() memory at bitmap when no longer required
 */
extern int node_name2bitmap (char *node_names, bool best_effort,
			     bitstr_t **bitmap);

/* Purge the contents of a node record */
extern void purge_node_rec (struct node_record *node_ptr);

/*
 * rehash_node - build a hash table of the node_record entries.
 * NOTE: manages memory for node_hash_table
 */
extern void rehash_node (void);

/* Convert a node state string to it's equivalent enum value */
extern int state_str2int(const char *state_str, char *node_name);

/* (re)set cr_node_num_cores arrays */
extern void cr_init_global_core_data(struct node_record *node_ptr,
				     int node_cnt, uint16_t fast_schedule);

extern void cr_fini_global_core_data(void);

/*return the coremap index to the first core of the given node */
extern uint32_t cr_get_coremap_offset(uint32_t node_index);

/* Return a bitmap the size of the machine in cores. On a Bluegene
 * system it will return a bitmap in cnodes. */
extern bitstr_t *cr_create_cluster_core_bitmap(int core_mult);

/* Given the number of tasks per core and the actual number of hw threads,
 * compute how many CPUs are "visible" and, hence, usable on the node.
 */
extern int adjust_cpus_nppcu(uint16_t ntasks_per_core, uint16_t threads,
			     int cpus);

/*
 * find_hostname - Given a position and a string of hosts, return the hostname
 *                 from that position.
 * IN pos - position in hosts you want returned.
 * IN hosts - string representing a hostlist of hosts.
 * RET - hostname or NULL on error.
 * NOTE: caller must xfree result.
 */
extern char *find_hostname(uint32_t pos, char *hosts);

#endif /* !_HAVE_NODE_CONF_H */
